<template>
  <div class="vue-tinymce">
    <!--富文本编辑器-->
    <g-spin
      :loading="!initial"
      :style="{ minHeight: Object.prototype.toString.call(height).slice(8, -1) == 'Number' ? `${height}px` : height }"
      type="rect"
      :zIndex="screenfull ? 9999 : 10"
      size="large"
    >
      <vue-tinymce
        v-if="loadedTinymceJs"
        :content="content"
        :setting="_setting"
        :setup="setup"
        @change="onChange"
        @on-remove-editor="onRemoveEditor"
        @on-before-unload="onBeforeUnload"
        ref="tinymceRef"
      ></vue-tinymce>
    </g-spin>

    <!--阿里云视频上传弹出框-->
    <custom-video @on-add-video="onAddVideo" ref="customVideoRef"></custom-video>

    <!--阿里云视频预览弹出框-->
    <custom-video-preview ref="customVideoPreviewRef"></custom-video-preview>

    <!--多图片上传弹出框-->
    <custom-multi-img @on-multi-img-success="onMultiImgSuccess" ref="customMultiImgRef"></custom-multi-img>

    <!--全屏左边 -->
    <div class="fullscreen-left" v-show="screenfull">
      <!--手机预览-->
      <div class="mobile__wrap" v-if="false">
        <svg
          t="1608454390278"
          class="icon"
          viewBox="0 0 1024 1024"
          version="1.1"
          xmlns="http://www.w3.org/2000/svg"
          p-id="2840"
          width="50"
          height="50"
        >
          <path
            d="M702.699388 60.945047 321.284238 60.945047c-57.463044 0-104.022314 46.591131-104.022314 104.018052l0 693.454702c0 57.426921 46.560293 104.019075 104.022314 104.019075l381.416174 0c57.463044 0 104.022314-46.592155 104.022314-104.019075L806.722726 164.963099C806.722726 107.537202 760.163456 60.945047 702.699388 60.945047zM477.317197 95.617731l69.349233 0c9.582632 0 17.336541 7.754614 17.336541 17.33583 0 9.582239-7.753909 17.336854-17.336541 17.336854l-69.349233 0c-9.581609 0-17.336541-7.754614-17.336541-17.336854C459.980656 103.372346 467.735588 95.617731 477.317197 95.617731zM511.992325 920.077116c-24.482581 0-44.324277-19.840884-44.324277-44.322461 0-24.480554 19.84272-44.322461 44.324277-44.322461 24.481557 0 44.324277 19.84293 44.324277 44.322461C556.317626 900.237255 536.473882 920.077116 511.992325 920.077116zM737.373493 771.736603c0 9.582239-7.753909 17.33583-17.336541 17.33583L303.946674 789.072433c-9.582632 0-17.337564-7.753591-17.337564-17.33583L286.60911 182.299953c0-9.582239 7.754932-17.33583 17.337564-17.33583l416.090278 0c9.582632 0 17.336541 7.754614 17.336541 17.33583L737.373493 771.736603z"
            fill="#515151"
            p-id="2841"
          ></path>
        </svg>
      </div>
    </div>

    <!--全屏右边 -->
    <div class="fullscreen-right" v-show="screenfull">
      <!--图片信息-->
      <custom-edit-img ref="customEditImgRef"></custom-edit-img>
    </div>
  </div>
</template>

<script>
import VueTinymce from './plugin/vue-tinymce'
import CustomVideoPreview from './plugin/custom-video-preview'
import CustomMultiImg from './plugin/custom-multi-img'
import CustomVideo from './plugin/custom-video'
import CustomEditImg from './plugin/custom-edit-img'
import { loadJS, uploadFileConfig, uploadFileName, qiniuErrorCode } from './utils/common'
import { mapActions, mapMutations } from 'vuex'
import IosLoading from './ios-loading--dark.gif'
import BUtils from '@bianpengfei/utils'
import axios from 'axios'
const htmls =
  'html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, ins, kbd, q, s, samp, small, strike,\n' +
  'strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody' +
  'tfoot, thead, tr, th, td, textarea, input, address, cite, dfn, em, var, i, table, button, input, select, textarea, section, br, h1, h2, ' +
  'th, h1, h2, h6, button, input, select, textarea'
const contentStyle = (height) => {
  return `body {min-height: ${height - 80}px} `
}

const customButtonIcons = {
  'custom-mobile-preview':
    '<svg t="1608454390278" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2840" width="22" height="22"><path d="M702.699388 60.945047 321.284238 60.945047c-57.463044 0-104.022314 46.591131-104.022314 104.018052l0 693.454702c0 57.426921 46.560293 104.019075 104.022314 104.019075l381.416174 0c57.463044 0 104.022314-46.592155 104.022314-104.019075L806.722726 164.963099C806.722726 107.537202 760.163456 60.945047 702.699388 60.945047zM477.317197 95.617731l69.349233 0c9.582632 0 17.336541 7.754614 17.336541 17.33583 0 9.582239-7.753909 17.336854-17.336541 17.336854l-69.349233 0c-9.581609 0-17.336541-7.754614-17.336541-17.336854C459.980656 103.372346 467.735588 95.617731 477.317197 95.617731zM511.992325 920.077116c-24.482581 0-44.324277-19.840884-44.324277-44.322461 0-24.480554 19.84272-44.322461 44.324277-44.322461 24.481557 0 44.324277 19.84293 44.324277 44.322461C556.317626 900.237255 536.473882 920.077116 511.992325 920.077116zM737.373493 771.736603c0 9.582239-7.753909 17.33583-17.336541 17.33583L303.946674 789.072433c-9.582632 0-17.337564-7.753591-17.337564-17.33583L286.60911 182.299953c0-9.582239 7.754932-17.33583 17.337564-17.33583l416.090278 0c9.582632 0 17.336541 7.754614 17.336541 17.33583L737.373493 771.736603z" fill="#47c479" p-id="2841"></path></svg>',
  'custom-save':
    '<svg t="1607771594069" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9264" width="19" height="19"><path d="M512 276.2c17.5 0 31.8-13.8 31.8-30.7V184c0-17-14.3-30.7-31.8-30.7-17.6 0-31.8 13.8-31.8 30.7v61.5c0 17 14.3 30.7 31.8 30.7z" p-id="9265" fill="#47c479"></path><path d="M933.4 263.8L758.1 90.1C741.4 73.2 719 64 695.1 64H153.6C104.4 64 64 104.4 64 153.6v716.7c0 49.3 40.4 89.6 89.6 89.6h716.7c49.3 0 89.6-40.4 89.6-89.6v-543c0.1-23.4-9.5-46.8-26.5-63.5z m-687.1 7.3V126.8h352.4v144.4c0 16.4-13.5 29.9-29.9 29.9H276.1c-16.4-0.1-29.8-13.5-29.8-30zM748 896.2H276V633.5c0-16.4 13.5-29.9 29.9-29.9h412.3c16.4 0 29.9 11.5 29.9 27.9v264.7z" p-id="9266" fill="#47c479"></path></svg>',
  'custom-video':
    '<svg t="1607851115488" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7949" width="23" height="23"><path d="M412.212808 649.951909l225.837538-113.578802c20.777209-10.408047 20.777209-40.274262 0-50.761104L412.212808 372.077204c-18.769482-9.428743-40.84322 4.239558-40.84322 25.374924l0 227.090065C371.369587 645.690862 393.442302 659.337673 412.212808 649.951909L412.212808 649.951909zM879.715361 170.295548 145.270083 170.295548c-46.444798 0-84.387969 38.575574-84.387969 85.619006l0 510.153956c0 47.264467 37.669948 85.588307 84.387969 85.588307l734.444255 0c46.422286 0 84.420715-38.47836 84.420715-85.588307L964.135052 255.915577C964.136076 208.66339 926.453848 170.295548 879.715361 170.295548L879.715361 170.295548zM230.247476 766.200516c0 15.869433-12.088316 28.668946-28.481681 28.668946l-55.95029 0c-15.717983 0-28.481681-12.122085-28.481681-28.668946l0-56.223512c0-15.813151 12.078083-28.64234 28.481681-28.64234l55.95029 0c15.685237 0 28.481681 12.164041 28.481681 28.64234L230.247476 766.200516 230.247476 766.200516zM230.247476 539.086915c0 15.871479-12.088316 28.690436-28.481681 28.690436l-55.95029 0c-15.717983 0-28.481681-12.166087-28.481681-28.690436l0-56.221466c0-15.83771 12.078083-28.6669 28.481681-28.6669l55.95029 0c15.685237 0 28.481681 12.164041 28.481681 28.6669L230.247476 539.086915 230.247476 539.086915zM230.247476 311.995827c0 15.847943-12.088316 28.64541-28.481681 28.64541l-55.95029 0c-15.717983 0-28.481681-12.098549-28.481681-28.64541l0-56.222489c0-15.83771 12.078083-28.6669 28.481681-28.6669l55.95029 0c15.685237 0 28.481681 12.164041 28.481681 28.6669L230.247476 311.995827 230.247476 311.995827zM738.297514 794.869463 286.698163 794.869463 286.698163 227.106438l451.599352 0L738.297514 794.869463 738.297514 794.869463zM907.662877 766.200516c0 15.869433-12.099572 28.668946-28.504194 28.668946l-55.95029 0c-15.694447 0-28.436656-12.122085-28.436656-28.668946l0-56.223512c0-15.813151 12.098549-28.64234 28.480658-28.64234l55.971779 0c15.652492 0 28.438703 12.164041 28.438703 28.64234L907.662877 766.200516 907.662877 766.200516zM907.662877 539.086915c0 15.871479-12.099572 28.690436-28.504194 28.690436l-55.95029 0c-15.694447 0-28.436656-12.166087-28.436656-28.690436l0-56.221466c0-15.83771 12.098549-28.6669 28.480658-28.6669l55.971779 0c15.652492 0 28.438703 12.164041 28.438703 28.6669L907.662877 539.086915 907.662877 539.086915zM907.662877 311.995827c0 15.847943-12.099572 28.64541-28.504194 28.64541l-55.95029 0c-15.694447 0-28.436656-12.098549-28.436656-28.64541l0-56.222489c0-15.83771 12.098549-28.6669 28.480658-28.6669l55.971779 0c15.652492 0 28.438703 12.164041 28.438703 28.6669L907.662877 311.995827 907.662877 311.995827zM907.662877 311.995827" p-id="7950" fill="#515151"></path></svg>',
  'custom-multi-img':
    '<svg viewBox="0 0 1280 1024" xmlns="http://www.w3.org/2000/svg" width="21" height="20"><path d="M1126.2,779.8V87.6c0-24-22.6-86.9-83.5-86.9H83.5C14.7,0.7,0,63.7,0,87.7v692c0,36.2,29.2,89.7,83.5,89.7l959.3-1.3c51.7,0,83.5-42.5,83.5-88.3zm-1044,4V86.3h961.6V783.7H82.2v0.1z" fill="#53565A"/><path d="M603,461.6L521.1,366.3,313,629.8,227.2,546.8,102.4,716.8H972.8v-170L768.2,235.2,603.1,461.6zM284.6,358.4a105.4,105.4,0,0,0,73.5-30c19.5-19.1,30.3-45,30.2-71.8,0-56.8-45.9-103-102.4-103-56.6,0-102.4,46.1-102.4,103C183.4,313.5,228,358.4,284.6,358.4z" fill="#9598A0"/><path d="M1197.7,153.6l-0.3,669.3s13.5,113.9-67.4,113.9H153.6c0,24.1,23.9,87.2,83.5,87.2h959.3c58.3,0,83.6-49.5,83.6-89.9V240.8c-0.1-41.8-44.9-87.2-82.3-87.2z" fill="#53565A"/></svg>',
  'custom-more':
    '<svg t="1620830581572" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1865" width="20" height="20"><path d="M862.2 562.2H162.3c-27.6 0-50-22.4-50-50s22.4-50 50-50h699.9c27.6 0 50 22.4 50 50s-22.4 50-50 50z" p-id="1866"></path><path d="M512.3 912.2c-27.6 0-50-22.4-50-50V162.3c0-27.6 22.4-50 50-50s50 22.4 50 50v699.9c0 27.6-22.4 50-50 50z" p-id="1867"></path></svg>'
}

const TINYMCE_CDN = 'https://unpkg.com/@bianpengfei/tinymce@0.1.6/tinymce.min.js' // cdn地址
const TINYMCE_CUSTOM_CSS = 'https://unpkg.com/@bianpengfei/tinymce@0.1.6/tinymce-custom.css' // tinymce自定义css

const $http = axios.create({
  timeout: 1000 * 30 // 请求超时时间 30s
})

export default {
  name: 'g-tinymce',
  props: {
    content: {
      // 内容
      type: String,
      default: ''
    },
    mode: {
      type: String,
      default: 'article' // 主题模式：simple  article
    },
    uploadImgMaxSize: {
      // 允许上传的图片大小
      type: Number, // 默认是5m
      default: 5
    },
    autoSave: {
      type: Boolean, // 是否自动保存
      default: false
    },
    intervalTime: {
      type: Number, // 自动保存时间
      default: 1000 * 60
    },
    menubar: {
      // 是否展示菜单
      type: Boolean,
      default: false
    },
    height: {
      // 编辑器高度
      type: Number,
      default: 420
    },
    toolbar: {
      // 工具  custom-video
      type: String,
      default:
        'fullscreen custom-save | styleselect formatpainter | bold italic underline forecolor backcolor | strikethrough | bullist numlist | alignleft aligncenter alignright alignjustify | quickimage custom-multi-img | link blockquote hr | codesample code removeformat custom-more '
    },
    fontsize_formats: {
      // 字体格式化
      type: String,
      default: '12px 13px 14px 15px 16px 17px 18px 20px 22px 24px 26px 28px 30px 40px 50px'
    },

    quickbars_selection_toolbar: {
      // 快捷工具  styleselect | bold italic | forecolor backcolor removeformat| alignleft aligncenter
      type: String,
      default: ''
    },

    link_target_list: {
      type: Array,
      default: () => [
        { title: '当前窗口', value: '' },
        { title: '新窗口', value: '_blank' },
        { title: 'webview', value: '_webview' }
      ]
    },
    style_formats: {
      // 段落格式
      type: Array,
      default: () => {
        return [
          {
            title: '标题(大字号)',
            inline: 'span',
            remove: 'all',
            classes: 'h1',
            split: true,
            expand: false,
            block_expand: false,
            exact: true,
            deep: true
          },
          {
            title: '标题(小字号)',
            inline: 'span',
            classes: 'h6',
            remove: 'all',
            split: true,
            expand: false,
            block_expand: false,
            exact: true,
            deep: true
          },
          {
            title: '正文(中字号)',
            inline: 'span',
            classes: 'p',
            remove: 'all',
            split: true,
            expand: false,
            block_expand: false,
            exact: true,
            deep: true
          }
        ]
      }
    },
    setting: {
      // 配置覆盖
      type: Object,
      default: () => ({})
    }
  },

  data() {
    return {
      screenfull: false,
      loadedTinymceJs: false,
      initial: false // 表示编辑器是否初始化结束
    }
  },

  model: {
    prop: 'content',
    event: 'on-change-content'
  },

  components: {
    VueTinymce,
    CustomVideoPreview,
    CustomMultiImg,
    CustomVideo,
    CustomEditImg
  },

  computed: {
    _setting() {
      return {
        height: this.height,
        menubar: this.menubar,
        statusbar: false,
        fontsize_formats: this.fontsize_formats,
        font_formats: this.font_formats,
        theme: 'silver',
        content_css: [TINYMCE_CUSTOM_CSS, this._mode],
        icons: 'custom',
        placeholder: '在这里输入文字',
        body_class: 'custom-tinymce',
        branding: false,
        paste_auto_cleanup_on_paste: false,
        paste_text_sticky: true,
        style_formats: this.style_formats,
        content_style: contentStyle(this.height),
        custom_colors: true,
        color_cols: 6,
        format_empty_lines: true,
        link_title: false,
        target_list: this.link_target_list,
        color_map: [
          '041C33',
          '#041C33',
          'FFFFFF',
          '#FFFFFF',
          'EB7400',
          '#EB7400',
          '666666',
          '#666666',
          'EB5757',
          '#EB5757',
          '1890FF',
          '#1890FF',
          'FFB46B',
          '#FFB46B',
          'FFACDA',
          '#FFACDA',
          'FFD900',
          '#FFD900',
          'FF8D8D',
          '#FF8D8D',
          '8BC7FF',
          '#8BC7FF',
          '7EFFF8',
          '#7EFFF8'
        ],
        imagetools_cors_hosts: ['**'],
        toolbar_sticky: false,
        resize: 'both',
        visual: false,
        quickbars_selection_toolbar: this.quickbars_selection_toolbar,
        contextmenu: '',
        contextmenu_never_use_native: false,
        toolbar: this.toolbar,
        toolbar_drawer: 'sliding',
        style_formats_autohide: false,
        a11y_advanced_options: true,
        style_formats_merge: false,
        codesample_global_prismjs: true,
        nonbreaking_force_tab: true, // 允许tab空格
        image_caption: true, // 图片标题
        powerpaste_word_import: 'merge', // 参数可以是propmt, merge, clear，效果自行切换对比
        powerpaste_html_import: 'merge', // propmt, merge, clear
        powerpaste_allow_local_images: true,
        paste_data_images: false, // 是否允许复制过来的图片自动上传
        auto_focus: true,
        paste_webkit_styles: 'all',
        // quickbars_selection_toolbar: false,
        advlist_bullet_styles: 'default',
        advlist_number_styles: 'default',
        autosave_ask_before_unload: true, // 关闭浏览器是否卸载  默认开启
        formats: {
          removeformat: [
            { selector: htmls, remove: 'all', split: true, expand: false, block_expand: true, deep: true },
            {
              selector: 'span',
              attributes: ['style', 'class'],
              remove: 'all',
              split: true,
              expand: false,
              deep: true
            },
            { selector: 'img', attributes: ['style', 'class'], split: false, expand: true, deep: true },
            { selector: '*', attributes: ['style', 'class'], split: false, expand: false, deep: true }
          ]
        },
        plugins: [
          'toc',
          'hr',
          'preview',
          'formatpainter',
          'advcode',
          'paste',
          'codesample',
          'textcolor',
          'colorpicker',
          'emoticons',
          'link',
          'image',
          'imagetools',
          'autosave',
          'table',
          'fullscreen',
          'quickbars',
          'lists',
          'advlist',
          'nonbreaking',
          'powerpaste'
        ],
        quickbars_insert_toolbar: '',
        autosave_restore_when_empty: false, // 当初始化时编辑器为空时，TinyMCE是否应自动恢复存储在本地存储中的内容
        language: 'zh_CN', //本地化设置
        typeahead_urls: true, // 默认开启，当在编辑区内输入网址并回车或按下空格时，TinyMCE会分析出你键入的可能是一个网址，并在自动给其加上链接。
        imagetools_fetch_image: (img) => {
          return new tinymce.util.Promise(function (resolve) {
            // Fetch the image and return a blob containing the image content
            resolve(new Blob())
          })
        },

        /**
         * TODO：初始化
         * 编辑器实例化后 回调函数
         * */
        init_instance_callback: async (editor) => {
          try {
            // eslint-disable-next-line vue/no-side-effects-in-computed-properties
            if (!this.container) this.container = editor.contentDocument
            setTimeout(() => {
              if (window.tippy) {
                window.tippy('.tox-toolbar-overlord .tox-toolbar__group>*', {
                  content(reference) {
                    const title = reference.getAttribute('title')
                    reference.removeAttribute('title')
                    return title
                  },
                  placement: 'bottom'
                })
              }
              this.initContentHeight()
              this.initAliplay()
              this.initImg()
              this.tinymceEvents()
              this.addAutoSaveDom()
              this.$emit('init', true)
              this.initial = true
            }, 20)
          } catch (e) {
            this.$message.error('编辑器加载错误：' + e.toString())
          }
        },

        /**
         * 上传图片回调地址 TODO
         * */
        images_upload_handler: async (blobInfo, success, failure, progress) => {
          const isLt2M = blobInfo.blob().size / 1024 / 1024 < this.uploadImgMaxSize // MB
          if (!isLt2M) {
            this.$message.error(`上传头像图片大小不能超过${this.uploadImgMaxSize}MB!`)
            failure(`上传头像图片大小不能超过${this.uploadImgMaxSize}MB!`, { remove: true })
            return
          }
          progress(100)
          progress && progress(0)
          const formData = new FormData()
          formData.append('token', this.qiNiuConfigGetter.token)
          formData.append('file', blobInfo.blob())
          formData.append('key', uploadFileName(blobInfo?.filename() || '.png', 'content'))
          let complete = 0
          const config = {
            onUploadProgress: (progressEvent) => {
              complete = ((progressEvent.loaded / progressEvent.total) * 100) | 0
              progress && progress(complete)
            },
            headers: {
              'Content-Type': 'multipart/form-data'
            }
          }
          $http
            .post(uploadFileConfig.qiNiuUrl, formData, config)
            .then((res) => {
              if (res.code) {
                const errMsg = qiniuErrorCode.find((item) => item.code == res.code)
                if (errMsg) {
                  this.$message.error(`图片上传失败，错误码：${res.code}, message：${errMsg.message}`)
                  return
                }
              }
              success(this.domain + res.data.key)
              progress(100)
            })
            .catch(async (err) => {
              console.error(err)
              failure('上传图片失败~ ' + err.toString(), { remove: true })
              this.$message.warning('上传失败！请重新上传')
            })
        },
        ...this.setting
      }
    },

    _mode() {
      const map = new Map([
        ['article', './tinymce/css/tinymce-custom-article.css'],
        ['simple', './tinymce/css/tinymce-custom-simple.css']
      ])
      return map.get(this.mode)
    }
  },

  watch: {
    content(newVal) {
      this.debounceContentChangeHandler(newVal)
    }
  },

  deactivated() {
    this.initial = false
    if (this.autoSave) {
      this.onAutoSaveEvent(this.content)
      if (this.timer) {
        clearInterval(this.timer)
        this.timer = null
      }
    }
  },

  async created() {
    if (!window.tinyMCE) {
      this.loadedTinymceJs = false
      await loadJS(TINYMCE_CDN)
    }
    if (window.tinyMCE) {
      this.loadedTinymceJs = true
    }
  },

  mounted() {
    this.debounceContentChangeHandler = this.$debounce(this.onContentChange, 500)
  },

  methods: {
    ...mapMutations(['setLoading']),
    ...mapActions(['getQiNiuToken']),

    setup(editor) {
      this._editor = editor

      /**
       * 插件创建 初始化
       * */
      editor.on('init', (e) => {
        console.log('The Editor has initialized.')
        if (!this.container) this.container = editor.contentDocument
      })

      /**
       * 监听全屏切换
       * */
      editor.on('FullscreenStateChanged', (e) => {
        const elBody = this.container.querySelector('body')
        const top = e?.target?.contentAreaContainer?.getBoundingClientRect()?.top || 41
        const marginTop = elBody?.getBoundingClientRect().top || 10
        if (e.state) {
          this.screenfull = true
          const clientHeight = document.documentElement.clientHeight || document.querySelector('body').clientHeight
          elBody.style.minHeight = `${clientHeight - top - 2 * marginTop}px`
        } else {
          this.screenfull = false
          this.$refs.customEditImgRef?.hide()
          elBody.style.minHeight = `${this.height - top - 2 * marginTop}px`
        }
      })

      /*
       * 内容滚动
       * */
      editor.on('ScrollContent', (e) => {
        if (e.target.querySelector('html').scrollTop > 20) {
          document.querySelector('.tox-editor-header').classList.add('tox-editor-header--active')
        } else {
          document.querySelector('.tox-editor-header').classList.remove('tox-editor-header--active')
        }
      })

      /*监听命令*/
      editor.on('ExecCommand', (element, parents, selectionChange) => {
        console.log(element, parents, selectionChange)
      })

      /**/
      editor.on('NodeChange', (command, ul, value) => {
        // console.log('NodeChange', command, ul, value)
      })

      // 自定义
      // 保存按钮
      editor.ui.registry.addButton('custom-save', {
        text: customButtonIcons['custom-save'],
        tooltip: '保存',
        onAction: () => {
          this.initImg()
          setTimeout(() => {
            this.onAutoSaveEvent(this.content, 'on-save')
          }, 20)
        }
      })

      // 自定义
      // 保存按钮
      editor.ui.registry.addMenuButton('custom-more', {
        text: customButtonIcons['custom-more'],
        tooltip: '插入更多内容',
        fetch: function (callback) {
          var items = [
            {
              type: 'menuitem',
              icon: 'user',
              text: 'Menu item 1',
              onAction: () => {
                // editor.execCommand('link')
                // editor.execCommand('mceInsertLink', true, 'https://www.tiny.cloud');
                // editor.execCommand('mceLink');
              }
            }
          ]
          callback(items)
        }
      })

      // 自定义
      // 视频
      editor.ui.registry.addButton('custom-video', {
        text: customButtonIcons['custom-video'],
        tooltip: '插入视频',
        onAction: () => {
          this.$refs.customVideoRef.show()
        }
      })

      // 自定义
      // 多图片上传
      editor.ui.registry.addButton('custom-multi-img', {
        text: customButtonIcons['custom-multi-img'],
        tooltip: '多图片上传',
        onAction: () => {
          this.$refs.customMultiImgRef.show()
        }
      })

      // 自定义
      // 手机预览
      editor.ui.registry.addButton('custom-mobile-preview', {
        text: customButtonIcons['custom-mobile-preview'],
        tooltip: '手机预览',
        onAction: () => {
          this.$emit('on-mobile-preview')
        }
      })
    },

    initContentHeight() {
      if (!this.container) this.container = this._editor.contentDocument
      const elBody = this.container.querySelector('body')
      const marginTop = elBody?.getBoundingClientRect().top || 10
      elBody.style.minHeight = `${this.height - 60 - 2 * marginTop}px`
    },

    /**
     * 内容变化
     * */
    @BUtils.debounceDtor(500)
    onContentChange(newVal) {
      setTimeout(() => {
        this.initAliplay()
        this.initImg()
      }, 20)
      if (this.autoSave && !this.timer) {
        // 自动保存
        this.timer = setInterval(() => {
          this.onAutoSaveEvent(newVal)
        }, this.intervalTime)
      }
    },

    /**
     * 自动保存事件
     * @param val 富文本内容
     * @param eventName 事件名称
     * */
    onAutoSaveEvent(val, eventName = 'on-auto-save') {
      this._elAutoSaveLoding && (this._elAutoSaveLoding.style.display = 'flex')
      this._elAutoSaveSuccess && (this._elAutoSaveSuccess.style.display = 'none')
      this._elAutoSaveError && (this._elAutoSaveError.style.display = 'none')
      this.$emit(
        eventName,
        val,
        () => {
          // 成功
          this._elAutoSaveLoding && (this._elAutoSaveLoding.style.display = 'none')
          if (this._elAutoSaveLoding) {
            this._elAutoSaveSuccess.style.display = 'flex'
            this._elAutoSaveSuccess.querySelector('div').innerHTML = `保存成功，上次更新：${this.$moment().format(
              'YYYY-MM-DD hh:mm:ss'
            )}`
            // setTimeout(() => {
            //   this._elAutoSaveSuccess.style.display = 'none'
            // }, 1000 * 4)
          }
        },
        () => {
          // 失败
          this._elAutoSaveLoding && (this._elAutoSaveLoding.style.display = 'none')
          if (this._elAutoSaveLoding) {
            this._elAutoSaveError.style.display = 'flex'
            this._elAutoSaveError.querySelector('div').innerHTML = `保存失败，时间：${this.$moment().format(
              'YYYY-MM-DD hh:mm:ss'
            )}`
            // setTimeout(() => {
            //   this._elAutoSaveError.style.display = 'none'
            // }, 1000 * 4)
          }
        }
      )
    },

    /**
     * 多图片上传成功
     * @param html html代码块
     * */
    onMultiImgSuccess(html) {
      setTimeout(() => {
        this._editor.insertContent(html)
        this.$refs.customMultiImgRef.hide()
      }, 20)
    },

    /**
     * 添加视频
     * */
    onAddVideo(html) {
      setTimeout(() => {
        this._editor.insertContent(html)
        this.$refs.customVideoRef.hide()
      }, 20)
    },

    /**
     * 添加自动保存loading标识
     * */
    addAutoSaveDom() {
      const area = document.querySelector('.tox-editor-container .tox-edit-area')
      if (this.autoSave && area) {
        const loadingHtml = `<div class="tinymce-autosave__wrap tinymce-autosave__wrap--loading"><img src="${IosLoading}"><div>保存中...</div></div>`
        const successHtml = `<div class="tinymce-autosave__wrap tinymce-autosave__wrap--success"><i class="el-icon-success"></i><div>保存成功</div></div>`
        const errorHtml = `<div class="tinymce-autosave__wrap tinymce-autosave__wrap--error"><i class="el-icon-warning"></i><div>保存失败</div></div>`
        area.insertAdjacentHTML('afterbegin', loadingHtml)
        area.insertAdjacentHTML('afterbegin', successHtml)
        area.insertAdjacentHTML('afterbegin', errorHtml)
        setTimeout(() => {
          this._elAutoSaveLoding = document.querySelector('.tinymce-autosave__wrap--loading')
          this._elAutoSaveSuccess = document.querySelector('.tinymce-autosave__wrap--success')
          this._elAutoSaveError = document.querySelector('.tinymce-autosave__wrap--error')
        }, 20)
      }
    },

    onLoadImg(e) {
      e.width = e.clientWidth || 'auto'
      e.height = e.clientHeight || 'auto'
    },

    /**
     * 初始化 图片
     * */
    initImg() {
      const imgs = this.container && this.container.querySelectorAll('img')
      if (imgs) {
        for (let i = 0; i < imgs.length; i++) {
          const e = imgs[i]
          if (e.nodeType == 1) {
            if (e.clientWidth) {
              e.width = e.clientWidth
            }
            if (e.clientHeight) {
              e.height = e.clientHeight
            }
            e.onload = () => this.onLoadImg(e)
            const fn = () => {
              if (!this.screenfull) {
                return
              }
              this.$nextTick(() => {
                if (this.$refs.customEditImgRef) {
                  this.$refs.customEditImgRef.show()
                  this.$refs.customEditImgRef.setData(e)
                }
              })
            }
            // const debounceCallback = this.$debounce(fn, 500)
            // const callback = mutationList => {
            //   console.log('mutationList', mutationList)
            //   debounceCallback(mutationList)
            // }
            // const observer = new MutationObserver(callback)
            // observer.observe(e, { attributes: true, attributeFilter: ['width'], attributeOldValue: true })
            e.onclick = (event) => {
              this.currentImg = e
              fn()
            }
          }
        }
      }
    },

    /**
     * 初始化 阿里播放器
     * */
    initAliplay() {
      return new Promise((resolve) => {
        if (!this.container) this.container = this._editor.contentDocument
        if (!this.container) return
        const aliplayerEls = this.container.querySelectorAll('.custom-alipay-video')
        for (let i in aliplayerEls) {
          const el = aliplayerEls[i]
          if (el.nodeType == 1) {
            el.onclick = () => {
              this.$refs.customVideoPreviewRef.show()
              const source = el.getAttribute('data-src')
              const cover = el.getAttribute('data-cover')
              this.$nextTick(() => {
                try {
                  new Aliplayer(
                    {
                      id: 'aliplay-video',
                      source,
                      cover,
                      width: '100%',
                      height: '550px',
                      autoplay: true,
                      isLive: false,
                      rePlay: true,
                      playsinline: true,
                      preload: true,
                      controlBarVisibility: 'hover',
                      useH5Prism: true,
                      skinLayout: [
                        {
                          name: 'bigPlayButton',
                          align: 'blabs',
                          x: 30,
                          y: 80
                        },
                        {
                          name: 'H5Loading',
                          align: 'cc'
                        },
                        {
                          name: 'tooltip',
                          align: 'blabs',
                          x: 0,
                          y: 56
                        },
                        {
                          name: 'thumbnail'
                        },
                        {
                          name: 'controlBar',
                          align: 'blabs',
                          x: 0,
                          y: 0,
                          children: [
                            {
                              name: 'progress',
                              align: 'blabs',
                              x: 0,
                              y: 44
                            },
                            {
                              name: 'playButton',
                              align: 'tl',
                              x: 15,
                              y: 12
                            },
                            {
                              name: 'fullScreenButton',
                              align: 'tr',
                              x: 10,
                              y: 12
                            },
                            {
                              name: 'volume',
                              align: 'tr',
                              x: 5,
                              y: 10
                            }
                          ]
                        }
                      ]
                    },
                    (player) => {
                      this.$refs.customVideoPreviewRef.setInitial(true)
                      console.log('The player is created')
                    }
                  )
                } catch (e) {
                  this.$message.error(e.toString())
                }
              })
            }
          }
        }
        console.log(aliplayerEls)
        resolve()
      })
    },

    tinymceEvents() {
      if (window.tinymce) {
        /**
         * 监听格式化操作
         * */
        window.tinymce.activeEditor.formatter.formatChanged(
          'alignleft,aligncenter,alignright',
          (val) => {
            if (val && this.screenfull && this.currentImg) {
              this.$nextTick(() => {
                if (this.$refs.customEditImgRef) {
                  this.$refs.customEditImgRef.setData(this.currentImg)
                }
              })
            }
          },
          true
        )
        window.tinymce.activeEditor.on('click', (e) => {
          if (e.target.nodeName != 'IMG') {
            if (this.$refs.customEditImgRef) {
              this.currentImg = null
              this.$refs.customEditImgRef.hide()
            }
          }
        })
        // 节点大小变化
        window.tinymce.activeEditor.on('ObjectResized', (e) => {
          if (e.target.nodeName == 'IMG') {
            // Prevent resize
            if (this.screenfull) {
              this.$nextTick(() => {
                if (this.$refs.customEditImgRef) {
                  this.$refs.customEditImgRef.show()
                  this.$refs.customEditImgRef.setData(e.target)
                }
              })
            }
          }
        })
      }
    },

    /**
     * 重置内容
     * */
    resetEditor() {
      this._editor.setContent('')
    },

    /**
     * 移除编辑器
     * */
    onRemoveEditor(editor, editorId) {
      this.$emit('destory', editor, editorId)
      if (this.timer) {
        clearInterval(this.timer)
        this.timer = null
      }
    },

    /**
     * 关闭窗口
     * */
    onBeforeUnload(editor) {
      this.$emit('on-window-unload', editor)
    },

    /**
     * 内容变化
     * */
    onChange(val) {
      this.$emit('on-change-content', val)
    }
  },

  beforeDestroy() {
    if (this.timer) {
      clearInterval(this.timer)
      this.timer = null
    }
  }
}
</script>

<style lang="scss" scoped></style>

<style lang="scss">
.custom-tinymce {
}
.tox-collection__item-label {
  h1,
  h2,
  h3,
  h4,
  h5,
  h6,
  pre,
  * {
    background: transparent !important;
  }
}
iframe.tox-edit-area__iframe {
  display: flex;
  justify-content: center;
  align-items: center;
}
</style>

<!--tinymce样式-->
<style lang="scss">
$button-primary-color: $--color-primary;
$success-color: $--color-success;
.mce-content-body:not(.mce-visualblocks)::before {
  left: 100px;
}
.tox {
  .tox-dialog__body-nav-item--active {
    border-bottom: 2px solid $button-primary-color !important;
    color: $button-primary-color !important;
  }
}
.tox-tiered-menu {
  .tox-swatches {
    padding: 0 5px 5px 5px;
    transition: none;
    .tox-swatches__row {
      .tox-swatch + .tox-swatch {
        margin-left: 4px;
      }
      .tox-swatch--remove {
        display: none;
      }
      .tox-swatch {
        width: 23px;
        margin-top: 5px;
        height: 23px;
        cursor: pointer;
        box-sizing: border-box;
        border: 1px solid #e8e8e8;
        border-radius: 3px;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: none;
        &:hover {
        }
      }
    }
  }
}
.tox .tox-tbtn--bespoke .tox-tbtn__select-label {
  text-align: center;
}
.tox-tinymce-aux {
  z-index: 4000 !important;
  .tox-collection__group {
    .tox-collection__item {
      padding-left: 0 !important;
      padding-right: 16px !important;
      display: flex;
      .tox-collection__item-label {
        order: 2;
      }
      .tox-collection__item-checkmark {
        order: 1;
        width: 30px !important;
        margin-left: 0 !important;
      }
    }
  }
  .tox-pop.tox-pop--top::before {
    border-color: transparent transparent #e8e8e8 transparent !important;
  }
  .tox-collection__item--enabled {
    .tox-collection__item-checkmark {
      svg {
        transform: scale(0.6);
        color: #8c8c8c;
      }
    }
  }
  .tox-pop__dialog {
    height: 38px;
    box-sizing: border-box;
    border: 1px solid #e8e8e8 !important;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.08) !important;
    .tox-toolbar__group:not(:last-of-type) {
      border-right: 1px solid #e8e8e8 !important;
    }
    .tox-toolbar__group {
      .tox-icon {
        cursor: pointer;
        svg {
          transform: scale(0.9);
        }
      }
      .tox-tbtn {
        height: 30px;
      }
    }
  }
  .tox-dialog-wrap__backdrop {
    background: rgba(0, 0, 0, 0.4) !important;
  }
  .tox-dialog {
    border-radius: 4px;
    border: none !important;
    //max-width: 800px !important;
    .tox-dialog__header {
      padding-bottom: 10px;
      border-bottom: 1px solid #ccc;
      .tox-dialog__title {
        font-size: 16px;
        font-weight: bold;
      }
    }
    .tox-dialog__body-content {
      padding-top: 10px;
      .tox-form {
        .tox-form__group {
          margin-bottom: 15px;
          .tox-label {
            line-height: 32px;
          }
        }
      }
    }
    .tox-dialog__footer {
      border-top: none;
    }
    .tox-dialog__footer-end {
      .tox-button {
        padding: 3px 20px !important;
        margin: 0 0 10px 0;
        background: $button-primary-color;
        font-weight: 500 !important;
        border: none;
        &:hover {
          background: $button-primary-color;
          opacity: 0.8;
        }
      }
      .tox-button--secondary {
        background: #f0f0f0;
        &:hover {
          background: #f0f0f0;
          opacity: 0.8;
        }
      }
    }
  }
}
.tox .tox-selectfield select:focus,
.tox .tox-listboxfield .tox-listbox--select:focus,
.tox .tox-textarea:focus,
.tox .tox-textfield:focus {
  border-color: $button-primary-color !important;
}

.tox .tox-dialog__body-content {
  input {
    height: 32px;
    min-height: 32px;
    box-sizing: border-box;
  }
}

.tox-menu {
  border: 1px solid #e8e8e8 !important;
}

.vue-tinymce {
  //min-width: 900px;
  position: relative;
  .tox-tinymce {
    border: 1px solid #e8e8e8;
    box-shadow: 0 2px 8px rgba(115, 115, 115, 0.08) !important;
  }

  .tinymce-autosave__wrap {
    font-size: 12px;
    color: #8c8c8c;
    position: absolute;
    z-index: 1900;
    width: 100%;
    bottom: 0;
    right: 15px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    border-radius: 4px;
    padding: 0 0 0 10px;
    user-select: none;
    height: 25px;
    img {
      width: 14px;
      height: 14px;
      margin-right: 5px;
    }
    div {
      font-size: 12px;
      width: fit-content;
      text-align: center;
    }
  }

  .tinymce-autosave__wrap--loading {
    display: none;
  }

  .tinymce-autosave__wrap--success {
    display: none;
    color: $success-color;
    background-color: #f0f9eb;
    i {
      font-size: 15px;
      display: inline-block;
      margin-right: 5px;
    }
  }
  .tinymce-autosave__wrap--error {
    display: none;
    background-color: #fef0f0;
    color: red;
    i {
      font-size: 15px;
      display: inline-block;
      margin-right: 5px;
    }
  }

  .tox-editor-header--active {
    background: #f9f9f9 !important;
    border-bottom: 1px solid #d9d9d9 !important;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.08) !important;

    .tox-toolbar__primary {
      border-bottom: 1px solid #d9d9d9 !important;
    }
  }

  .tox-editor-container {
    .tox-editor-header {
      background: #fcfcfc;
      border-bottom: 1px solid #e8e8e8;
      //border-bottom: 1px solid #e8e8e8;
      //display: flex;
      //justify-content: center;
      //flex-wrap: wrap;
      width: 100%;
      height: 40px;
      box-sizing: border-box;

      .tox-toolbar-overlord {
        width: fit-content;
        margin: auto;
      }

      .tox-toolbar__primary {
        background: none;
        background: #fcfcfc;
        border-bottom: 1px solid #e8e8e8;
      }

      .tox-toolbar__group:not(:last-of-type) {
        border-right: 1px solid #e8e8e8 !important;
      }
    }
  }

  .custom-tinymce {
    div {
    }
  }

  .tox-editor-container {
    .tox-toolbar__group {
      .tox-tbtn {
        cursor: pointer;
        svg {
          cursor: pointer;
          transform: scale(0.9);
        }
      }
    }
  }
}

/*选中文字自动弹出选项*/
.tox-silver-sink {
  .tox-tbtn {
    cursor: pointer;
    svg {
      cursor: pointer;
      transform: scale(0.8) !important;
    }
  }
  .tox-dialog {
    .tox-color-picker-container {
      justify-content: space-around;
      .tox-sv-palette {
        width: 280px;
        .tox-sv-palette-spectrum {
          width: 280px !important;
        }
      }
    }
  }
}
</style>

<!--element-->
<style lang="scss">
$button-primary-color: $--color-primary;
.el-dialog.tinymce {
  border-radius: 4px;
  .tinymce-button + .tinymce-button {
    margin-left: 6px;
  }
  .tinymce-button {
    line-height: 30px;
    background: $button-primary-color;
    cursor: pointer;
    display: inline-block;
    color: #fff;
    padding: 0 20px;
    border-radius: 2px;
    user-select: none;
    &:active {
      opacity: 0.8;
    }
  }
  .tinymce-button--cancel {
    background: #f0f0f0;
    color: #222f3e;
  }
  .el-dialog__header {
    border-bottom-color: #ccc;
    .el-dialog__title {
      font-size: 16px;
      font-weight: bold;
    }
  }
  .el-dialog__body {
    padding: 0;
    display: flex;
  }
}
</style>
